/**
 * Copyright (c) 2007-2008, stauren.net. All rights reserved.
 * version: 0.7.3
 * @author stauren@stauren.net
 */

(function(_scope) {
if (_scope['__'] == undefined) {
  _scope['__'] = {};
}
var __ = _scope['__'],
_defaultConfig = {
  debug : false,
  DU_TAG : '0.0.7',
  loaderBase : [
    '/misc', //production
    'http://double-underscore.googlecode.com/svn/tags', //google code base
    'http://double-underscore.googlecode.com/svn/yui/2.5.2/build',
    'http://localhost/stauren.net/develop/3party/yui252/build'
  ],
  loaderModules : {}
};

/**
 * @param {object} r reciever
 * @param {object} s source 
 * @param {boolean} override true to override properties with the same name in r, default to true
 */
__.objExtend = function(r, s, override) {
  override = override === false ? false : true; 
  for (var i in s) {
    if(override || typeof r[i] == 'undefined') {
      r[i] = s[i];
    }
  }
};

if (__.config == undefined) {
  __.config = {}
}
__.objExtend(__.config, _defaultConfig, false);

__.objExtend(__, {
  /**
   * listeners count
   */
  listeners : 0,

  /**
   * unified layer count
   */
  topLayer : 1,

  /**
   * modified from : http://ejohn.org/blog/simple-javascript-inheritance/
   * @example
   *  var Person = __.Class.extend({
   *    init: function(isDancing){
   *      this.dancing = isDancing;
   *    }
   *  });
   *
   *  var Ninja = Person.extend({
   *    init: function(){
   *      this._super( false );

   *    }
   *  });
   *
   *  var p = new Person(true);
   *  p.dancing; // => true
   *
   *  var n = new Ninja();
   *  n.dancing; // => false 
   */
  Class : 
  (function(){
    var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

    // The base Class implementation (does nothing)
    var Class = function(){};
   
    // Create a new Class that inherits from this class
    Class.extend = function(prop) {
      var _super = this.prototype;
    
      // Instantiate a base class (but only create the instance,
      // don't run the init constructor)
      initializing = true;
      var prototype = new this();
      initializing = false;
    
      // Copy the properties over onto the new prototype
      for (var name in prop) {
        // Check if we're overwriting an existing function
        prototype[name] = typeof prop[name] == "function" &&
          typeof _super[name] == "function" && fnTest.test(prop[name]) ?
          (function(name, fn){
            return function() {
              var tmp = this._super;
            
              // Add a new ._super() method that is the same method
              // but on the super-class
              this._super = _super[name];
            
              // The method only need to be bound temporarily, so we
              // remove it when we're done executing
              var ret = fn.apply(this, arguments);      
              this._super = tmp;
            
              return ret;
            };
          })(name, prop[name]) :
          prop[name];
      }
    
      // The dummy class constructor
      function Class() {
        // All construction is actually done in the init method
        if ( !initializing && this.init )
          this.init.apply(this, arguments);
      }
    
      // Populate our constructed prototype object
      Class.prototype = prototype;
    
      // Enforce the constructor to be what we expect
      Class.constructor = Class;

      // And make this class extendable
      Class.extend = arguments.callee;
    
      return Class;
    };
    return Class;
  })()
  ,

  /**
   * global variable leak check
   * usage : 
   *  __.globalCheck.init()
   * //...other scripts
   *
   */
  globalCheck : (function(){
    //from http://blog.jcoglan.com/2008/08/21/checking-your-javascript-for-variable-leaks/
    var Globals = {
      originals:   [],
      userDefined: [],
      warned:      [],
      root:        this,
      initialize: function() {
        if (this.originals.length > 0) return;
        for (var key in this.root) this.originals.push(key);
      },
      register: function() {
        for (var i = 0, n = arguments.length; i < n; i++)
          this.userDefined.push(arguments[i]);
      },
      check: function() {
        for (var key in this.root) {
          if (this.originals.indexOf(key) == -1
              && this.userDefined.indexOf(key) == -1
              && this.warned.indexOf(key) == -1) {
            console && console.warn('Global variable: ' + key);
            this.warned.push(key);
          }
        }
      },
      run: function() {
        var self = this;
        setInterval(function() { self.check() }, 1000);
      }
    };
    return {
      init : function() {
        Globals.register('__', 'YAHOO', '_FirebugCommandLine', '_firebug', '_FirebugConsole');
        Globals.initialize();    
        Globals.run();
      }
    }
  })()
  ,

  /**
   * get flash version of the browser
   */
  getFlashVersion : function (){
    var _ver = false, axo;
    if(navigator.plugins&&navigator.mimeTypes.length){
      var x=navigator.plugins["Shockwave Flash"];
      if(x&&x.description){
        _ver=x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split(".")[0];
      }
    } else {
      if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0) {
        axo=1;
        var _tempVer=3;
        while(axo) {
          try{
            _tempVer++;
            axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_tempVer);
            _ver=_tempVer;
          } catch(e) {
            axo=null;
          }
        }
      } else {
        try {
          axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
        } catch(e) {
          try {
            axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
            _ver=6;
            axo.AllowScriptAccess="always";
          } catch(e) {
            if(_ver==6){
              return _ver;
            }
          }
          try {
            axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
          } catch(e) {}
        }
        if(axo!=null) {
          _ver= axo.GetVariable("$version").split(" ")[1].split(",")[0];
        }
      }
    }
    return _ver;
  }
  ,

  /**
   * utilities
   */
  _ : {}

});

//in case loader is not included
if (__.toCall == undefined) {
  var _SC = __.config,
  _setNewvalue = function(varName,newValue){
    var bAry=varName.split(/\./);
    var d=window, key;
    for(var i=0,j=bAry.length-1;i<j;i++){
      d[bAry[i]] = d[bAry[i]] || {};
      d=d[bAry[i]]
    }
    key = bAry[bAry.length-1];
    return d[key] = newValue || (d[key] === undefined ? {} : d[key])
  },
  _getValue = function(varName,newValue){ //get value, and create the object link
    var bAry=varName.split(/\./);
    var d=window;
    for(var i=0,j=bAry.length;i<j;i++){
      d[bAry[i]] = d[bAry[i]] || {};
      d=d[bAry[i]]
    }
    return d
  }
  ,
  _isSet = function(varName){
    var bAry=varName.split(/\./),
      d=window;
    for(var i=0,j=bAry.length;i<j;i++){
      if (d[bAry[i]] == undefined) {
        return false;
      }
      d = d[bAry[i]];
    }
    return true;
  },
  _callFunction = function(fnCall, judge, iInterval) {
    iInterval = iInterval || 1000;
    var _fnJudge = typeof judge=='function' ? judge : function() {
      var _bRet = false;
      if(_isSet(judge)) {
        _bRet = true;
      }
      return _bRet;
    }, _sId;

    // do it now
    if (_fnJudge()) {
      fnCall();
    } else {
    //or later
      _sId = setInterval(function() {
        if(_fnJudge()) {
          clearInterval(_sId);
          fnCall();
        }
      }, iInterval);
    }
  },
  _loadFile = function(type,url,fn) {
    var head = document.getElementsByTagName("head")[0];
   /* if (false && !inHead) {
      //loadFile while page loading
      if(type=="script"){
        document.write('<scr'+'ipt src="'+url+'" type="text/javascript"><\/scr'+'ipt>')
      } else if(type=="css"){
        document.write('<link href="'+url+'" type="text/css" rel="stylesheet"></link>')
      }
    } else {*/
      //loadFile after page is loaded, lots of loading may crash IE
      var node, usera = __.config.ua;
      fn=typeof fn == 'function' ? fn : function(){};
      if(type=="script"){
        node = document.createElement('script');
        node.type = 'text/javascript';
        node.src = url;
        node.charset = 'utf-8';
      }else if(type=="css"){
        node = document.createElement('link');
        node.type = 'text/css';
        node.rel = 'stylesheet';
        node.href = url;
        node.charset = 'utf-8';
      }
      if (usera.ie) {
        node.onreadystatechange = function() {
          var rs = this.readyState;
          if ("loaded" === rs || "complete" === rs) {
            fn();
          }
        };
      } else if (usera.webkit) {
        if (type === "script") {
          node.addEventListener("load", function() {
            fn();
          });
        } 
      } else {
        node.onload = function() {
          fn();
        }
      }
      head.appendChild(node);
   // }
  }, _loadModuleByName = function(modName,getObj) {
    var loadingItem = _SC.loaderModules[":"+modName];
   /* if (getObj && getObj.dynamic) {
      inHead = !!getObj.dynamic;
    }*/
    if(!loadingItem){
      _loadFile('script', modName, getObj && getObj.onSuccess)
    } else {
      var type = (loadingItem.detailObj && loadingItem.detailObj.type) || 'script';
      _loadFile(type,loadingItem.get(getObj), getObj && getObj.onSuccess)
    }
  }, _load = function(n,getObj) {
    if (typeof n=='object' && n.length > 0) {
      for (var i=0,j=n.length;i<j;i++) {
        _loadModuleByName(n[i], getObj);
      }
    } else {
      n = n.split(' ');
      var newObj, firstN = n.shift();
      if (n.length >= 1)  {
        newObj = { 
          onSuccess : function() { _load(n.join(' '), getObj); }
        }
      } else {
        newObj = getObj;
      }

      _loadModuleByName(firstN, newObj);
    }
  }, _LoadModule = function (modName, detailObj) {
    this.mname = modName;
    this.detailObj = detailObj || {};
  }; 
  _LoadModule.prototype.get = function(getObj) {
    getObj = getObj || {};

    //default : local file
    var isDebug = _SC.debug === true ? true : false,
      type = this.detailObj['type'] || 'js',
      source = this.detailObj['source'] || 'DU',
      sBase, name = this.mname;

    switch (source) {
      case 'DU' :
        //product on double-undersocre, debug on local
        if (isDebug) {
          sBase = [_SC.loaderBase[0], type].join('/');
          name += '_comment';
        } else {
          var edition = getObj.version ? getObj.version : _SC.DU_TAG;
          sBase = [_SC.loaderBase[1], edition].join('/');
        }
        break;
      case 'YUI' :
        //product on double-undersocre, debug on local
        if (isDebug) {
          sBase = [_SC.loaderBase[3], this.detailObj['module'] ? this.detailObj['module'] : name].join('/');
          name += this.detailObj['beta'] ? '-beta' : '';
        } else {
          sBase = [_SC.loaderBase[2], name].join('/');
          name += (this.detailObj['beta'] ? '-beta' : '') + '-min';
        }
        break;
      case 'ST' :
        //product on stauren.net, debug on local
          sBase = [_SC.loaderBase[0], type].join('/');
        if (isDebug) {
          name += '_comment';
        }
        break;
    }

    name += type == 'css' ? '.css' : '.js';
    if (isDebug) {
      name += '?_t='+Math.random();
    }
    return [sBase, name].join('/')
  };

  var ua = navigator.userAgent, cua = _setNewvalue('__.config.ua');
  if ((/KHTML/).test(ua)) {
    cua.webkit = true;
  } else if (/Opera/.test(ua)) {
    cua.opera = true;
  } else if (/MSIE/.test(ua)) {
    cua.ie = true;
  } else if (/Gecko/.test(ua)) {
    cua.gecko = true;
  }

  var loadingList = _SC.loaderModules;
  loadingList[":bcss"]=new _LoadModule("base", {type:'css', source:'ST'});
  loadingList[":stcss"]=new _LoadModule("stauren", {type:'css', source:'ST'});
  loadingList[":b-stcss"]=new _LoadModule("base-stauren", {type:'css', source:'ST'});

  loadingList[":yeditorcss"]=new _LoadModule("yeditor", {type:'css', source:'ST'});
  loadingList[":yeditor"]=new _LoadModule("yeditor",{source:'ST'});

  //loadingList[":stauren"]=new _LoadModule("stauren", {source:'ST'});
  loadingList[":validator"]=new _LoadModule("validator", {source:'ST'});

  loadingList[":es"]=new _LoadModule("es", {source:'DU'});
  loadingList[":stbase"]=new _LoadModule("base", {source:'DU'});
  loadingList[":imagecropper"]=new _LoadModule("image_cropper", {source:'DU'});
  //loadingList[":yui252"]=new _LoadModule("yui252", {source:'DU'});

  __.load = _load;
  __.set = _setNewvalue;
  __.get = _getValue;
  __.isSet = _isSet;
  __.toCall = _callFunction;
}

__.toCall(function() {
  var _YU = YAHOO.util,
  _YL = YAHOO.lang,
  _D = _YU.Dom,
  _E = _YU.Event,
  _S = _YU.Selector,
  _C = _YU.Connect,
  _CK = _YU.Cookie,
  _JSON = _YL.JSON,
  _SC = __.config,
  _ = __._,

  _EF = function() {},
  _K = function(x) {return x},

  _NODE_TYPE = {
    ELEMENT_NODE: 1,
    ATTRIBUTE_NODE: 2,
    TEXT_NODE: 3,
    CDATA_SECTION_NODE: 4,
    ENTITY_REFERENCE_NODE: 5,
    ENTITY_NODE: 6,
    PROCESSING_INSTRUCTION_NODE: 7,
    COMMENT_NODE: 8,
    DOCUMENT_NODE: 9,
    DOCUMENT_TYPE_NODE: 10,
    DOCUMENT_FRAGMENT_NODE: 11,
    NOTATION_NODE: 12
  }
  ,

  _OP = {
    "+": function(a, b){return a + b},
    "-": function(a, b){return a - b},
    "*": function(a, b){return a * b},
    "/": function(a, b){return a / b},
    "%": function(a, b){return a % b},
    "-2": function(a, b){return b - a},
    "/2": function(a, b){return b / a},
    "%2": function(a, b){return b % a},
    ">": function(a, b){return a > b},
    "<": function(a, b){return a < b},
    ">=": function(a, b){return a >= b},
    "<=": function(a, b){return a <= b},
    "==": function(a, b){return a == b},
    "===": function(a, b){return a === b},
    "&&": function(a, b){return a && b},
    "||": function(a, b){return a || b},
    "&": function(a, b){return a & b},
    "|": function(a, b){return a | b},
    "^": function(a, b){return a ^ b},
    "++": function(a){return a + 1},
    "--": function(a){return a - 1},
    "!": function(a){return !a}
  }
  ,

  /**
   * base function
   */
  /**
   * private function used to get Dom element
   * @param {string|array} sQuery an Id or a CSS selector string
   * @param {object} root dom reference of the root
   * @param {boolean} firstOnly stop after found the first el
   * @return {array} array of Dom elements
   */
  _$ = function(sQuery, root, firstOnly) {
    var _els = _D.get(sQuery);
    if (_els === null || root) {
      _els = _S ? _S.query(sQuery, root, firstOnly) : [];
    }
    if (!_YL.isArray(_els)) {
      _els = [_els];
    }
    return _els;
  }
  ,
  /**
   * private function to log message to console when in debug mode 
   * @param {object} obj info to be log
   * @param {object} bVarDump use var dump or not
   */
  _log = function(obj, bVarDump) {
    var d = window, _dt, sTime;
    //d.location.hash == '#debug' && 
    if (_SC.debug && d.console && d.console.log) {
      _dt = new Date();
      bVarDump && (obj = _dump(obj));
      sTime = ['(', _dt.getFullYear(), '-', (_dt.getMonth()+1), '-', _dt.getDate(), ' ',
        _dt.getHours(), ':', _dt.getMinutes(), ':', _dt.getSeconds(), ') '].join('');
      d.console.log(sTime, obj);
      return sTime + obj;
    }
  }
  ,

  _getCookie = function(name) {
    return _CK.get(name);
  }
  ,

  _setCookie = function(name, value) {
    return _CK.set(name, value);
  }
  ,

  /**
   * @param {integer} start the first number (could be ignored as 0)
   * @param {integer} end the last number < end
   * @param {integer} pace
   */
  _range = function(start, end, pace) {
    pace = pace || 1;
    var aReturn = [];
    if (end === undefined) {
      end = start;
      start = 0;
    }
    while(end > start) {
      aReturn[aReturn.length] = start;
      start += pace;
    }
    return aReturn;
  }
  ,

  /**
   * @param {array|object|object(to be traversed)} aAry
   * @param {function} fn callback function accept 2 params, array element value and index
   * @param {boolean} bIsObject if the aAry is not an array, false=treat as 1 element array, true=tranverse the object
   */
  _all = function(aAry, fn, bIsObject) {
    var i, j;
    if (!aAry) {
      return ;
    }
    if (bIsObject) {
      for(i in aAry) {
         if (!fn(aAry[i], i)) {
           return false;
         }
      }
    } else {
      //  splice failed for Nodelist
      //  if (typeof aAry.length !== 'number' || typeof aAry.splice !== 'function') 
      if (typeof aAry.length !== 'number') {
        //not an array
        aAry = [aAry];
      }
      for(i=0,j=aAry.length;i<j;i++) {
         if (!fn(aAry[i], i)) {
           return false;
         }
      }
    }
    return true;
  }
  ,

  /**
   * @param {array|object|object(to be traversed)} aAry
   * @param {function} fn callback function accept 2 params, array element value and index
   * @param {boolean} bIsObject if the aAry is not an array, false=treat as 1 element array, true=tranverse the object
   */
  _any = function(aAry, fn, bIsObject) {
    var i, j;
    if (!aAry) {
      return;
    }
    if (bIsObject) {
      for(i in aAry) {
        if (fn(aAry[i], i)) {
          return true;
        }
      }
    } else {
      if (typeof aAry.length !== 'number') {
        aAry = [aAry];
      }
      for(i=0,j=aAry.length;i<j;i++) {
        if (fn(aAry[i], i)) {
          return true;
        }
      }
    }
    return false;
  }
  ,

  /**
   * @param {array|object|object(to be traversed)} aAry
   * @param {function} fn callback function accept 2 params, array element value and index
   * @param {boolean} bIsObject if the aAry is not an array, false=treat as 1 element array, true=tranverse the object
   */
  _each = function(aAry, fn, bIsObject) {
    var i,j;
    if (!aAry) {
      return;
    }
    if (bIsObject) {
      for(i in aAry) {
        fn(aAry[i], i)
      }
    } else {
      //  splice failed for Nodelist
      //  if (typeof aAry.length !== 'number' || typeof aAry.splice !== 'function') 
      if (typeof aAry.length !== 'number') {
        //not an array
        aAry = [aAry];
      }
      for(i=0,j=aAry.length;i<j;i++) {
        fn(aAry[i], i);
      }
    }
  }
  ,

  /**
   * @param {function} fn callback function, accepts 3 params, base, array element value and index
   * @param {mixed} base 
   * @param {array|object} aAry accept an array or a single element
   * @param {boolean} bIsObj
   */
  _reduce = function(aAry, fn, base, bIsObj) {
    _each(aAry, function(oItem, i){
      base = fn(base, oItem, i)
    }, bIsObj);
    return base;
  }
  ,
  /**
   * first
   * @param {string|array} sQuery an Id or a CSS selector string
   */
  _f = function(sQuery) {
    return _$(sQuery)[0];
  }
  ,

  /**
   * @param {string|array} sQuery an Id or a CSS selector string
   */
  _v = function(sQuery) {
    var o = _$(sQuery)[0];
    if (o) {
      return o.value;
    }
    return false;
  }
  ,

  /**
   * @param {array|object} aAry
   * @param {function} fn callback function, accept 2 params, array element value and index
   * @param {boolean} bIsObj
   */
  _map = function(aAry, fn, bIsObj) {
    var aNew = [];
    _each(aAry, function(oItem, i) {
      aNew[i] = fn(oItem);
    }, bIsObj);
    return aNew;
  }
  ,

  /**
   * turn some thing in to an array
   */
  _a = function(aAry) {
    if (!aAry) return [];
    var length = aAry.length || 0, results = new Array(length);
    while (length--) results[length] = aAry[length];
    return results;
  }
  ,

  _w = function (str) {
    if (!_isString(str)) return [];
    str = _trim(str);
    return str ? str.split(/\s+/) : [];
  }
  ,

  /**
   * get unique array
   */
  _unique = function(aAry, sorted) {
    return _reduce(aAry, function(array, value, index) {
      if (0 == index || (sorted ? array[array.length-1] != value : !_inArray(value, array, true)))
        array.push(value);
      return array;
    }, []);
  }
  ,

  /**
   * 
   */
  _eachin = function (obj, fn) {
    var hp = Object.prototype.hasOwnProperty;
    for (var p in obj) {
      hp.call(obj, p) && fn(obj[p], p);
    }
  }
  ,

  /**
   * function to create function with prefilled param
   * @param {function|string} fn string must be a _OP index
   */
  _curry = function(fn) {
    typeof fn == 'string' && _OP[fn] && (fn = _OP[fn]);
    var argu = _a(arguments);
    argu.shift();
    return function() {
      return fn.apply(null, argu.concat(_a(arguments)))
    }
  }
  ,

  /**
   * function to get the keys of an array as an array
   * @param {array} aAry 
   */
  _keys = function(aAry) {
    var aKeys = [];
    _each(aAry, function(o,i) {
      aKeys.push(i);
    }, true);
    return aKeys
  }
  ,

  /**
   * function to get the values of an array as an array
   * @param {array} aAry 
   */
  _values = function(aAry) {
    var aValues = [];
    _each(aAry, function(o,i) {
      aValues.push(o)
    }, true);
    return aValues
  }
  ,

  /**
   * function to compose 2 functions
   * @param {function} fnWrap 
   * @param {function} fnParam 
   */
  _compose = function(fnWrap, fnParam) {
    return function() {
      return fnWrap(fnParam.apply(null, arguments))
    }
  }
  ,

  /**
   * function to generate a negative functions
   * @param {function} fn 
   */
  _negate = function(fn) {
    return function() {
      return !fn.apply(null, arguments)
    }
  }
  ,

  /**
   * like var_dump in php 
   * @param {object} obj things to be dump
   * @param {mixed} level how many levels to expand, default to 1, set to true to expand all levels
   */
  _dump = function(obj, level) {
    var content = '';
    if (_isFunction(obj)) {
      content = 'Function(' + obj.toString() + ')';
    } else if (_isObject(obj) || _isArray(obj)) {
      var len = 0;
      if (level !== true) {
        level = parseInt(level, 10);
        level = _isNumber(level) ? level : 1;
        level--;
      }
      if (level === true || level >= 0) {
        for (var key in obj) {
          var value = obj[key];
          content += '\n' + key + ':' + _dump(value, level) + ',';
          len++;
        }
        /**
         * some cases there are a length and values, (arguments)
         */
        if(obj.length && len == 0) {
          len=obj.length;
          for (var i=0;i<len;i++) {
            content += '\n' + i + ':' + _dump(obj[i], level) + ',';
          }
        }
        if (_isArray(obj)) {
          content = 'Array(' + len +') [' + content.substr(0, content.length-1) + '\n]';
        } else {
          content = 'Object(' + len +') {' + content.substr(0, content.length-1) + '\n}';
        }
      } else {
        content = _isArray(obj) ? 'Array['+ obj.length +']' : 'Object[object]';
      }
    } else if (_isString(obj)) {
      content = 'String(' + obj.length + ') "' + obj + '"';
    } else if (_isNumber(obj)) {
      content = 'Number(' + obj + ')';
    } else if (typeof obj == 'number') {
      if (isNaN(obj)){
        content = 'NaN(NaN)';
      } else if (!isFinite(obj)) {
        content = 'Infinity(' + obj.toString() + ')';
      }
    } else if (_isBoolean(obj)) {
      content = 'Bool(' + obj.toString() + ')';
    } else if (obj === null) {
      content = 'Null(null)';
    } else if (typeof obj === 'undefined') {
      content = 'Undefined(undefined)';
    } else {
      content = 'Unknowntype(unknown)'
    }
    return content;
  }
  ,

  /**
   * Based on John Resig's Array Remove
   */
  _arrayRemove = function(ary, from, to) {
    var rest, len=ary.length;
    from = from<0 ? from-0+len : from;
    to = to<0 ? to-0+len : to;
    if (to<from || from>=len || to>=len) {
      return false;
    }
    rest = ary.slice((to || from) + 1 || ary.length);
    ary.length = from < 0 ? ary.length + from : from;
    return ary.push.apply(ary, rest);
  }
  ,

  /**
   * Language utils
   */

  _getMergedObj = function(oldOne, newOne) {
    var _newO = {}, i;
    for(i in oldOne) {
      _newO[i] = oldOne[i]
    }
    for(i in newOne) {
      _newO[i] = newOne[i]
    }
    return _newO;
  }
  ,
  _isArray = function(obj) {
    return _YL.isArray(obj);
  }
  ,
  _isUndefined = function(obj) {
    return typeof obj === 'undefined';
  }
  ,
  _isNull = function(obj) {
    return obj === null;
  }
  ,
  _isBoolean = function(obj) {
    return _YL.isBoolean(obj);
  }
  ,
  _isFunction = function(obj) {
    return _YL.isFunction(obj);
  }
  ,
  _isNumber = function(obj) {
    return _YL.isNumber(obj);
  }
  ,
  _isInt = function(obj) {
    var iV = parseInt(obj);
    if (isNaN(iV)) return false;
    return obj==iV && obj.toString()==iV.toString(); 
  }
  ,
  _isFloat = function(obj) {
    // T_T has problem detect 1.2e5
    var fV = parseFloat(obj);
    if (isNaN(fV)) return false;
    return obj==fV && /\./.test(obj)
  }
  ,
  _isObject = function(obj) {
    return _YL.isObject(obj);
  }
  ,
  _isString = function(obj) {
    return _YL.isString(obj);
  }
  ,
  _isEmpty = function(obj) {
    return obj===null || typeof obj=== 'undefined' || obj === 0 
      || obj === '' || (typeof obj.length==='number' && obj.length == 0);
  }
  ,
  _isNode = function(obj, strict) {
    return _isObject(obj) && ((!strict && (obj==window || obj==document)) ||
      obj.nodeType == _NODE_TYPE.ELEMENT_NODE);
  }
  ,
  /**
   * return false or an array of index of the found values
   */
  _inArray = function(obj, ary, strict) {
    var found = false;
    _each(ary, function(oItem, i) {
      if(oItem===obj || (!strict && oItem==obj)) {
        found === false && (found = []);
        found[found.length] = i;
      }
    });
    return found;
  }
  ,

  /**
   * String utils
   */

  /**
   * from http://blog.stevenlevithan.com/archives/faster-trim-javascript
   * faster trim a string
   */
  _trim = function(str) {
    str = str.replace(/^\s\s*/, '');
    var ws = /\s/,
      i = str.length;
    while (ws.test(str.charAt(--i)));
    return str.slice(0, i + 1);
  }
  ,
  
  _truncate = function(str, len, truncation) {
    len = len || 30;
    truncation = typeof truncation == 'undefined' ? '...' : truncation;
    return str.length > len ?
      str.slice(0, len - truncation.length) + truncation : String(str);
  }
  ,

  _strRepeat= function(str, times) {
    var result = [];
    _each(_range(times), function() {
      result[result.length] = str;
    });
    return result.join('');
  }
  ,

  _notationShift = function(num, to, from) {
    if (!num || !to) {
      return false;
    }
    num = String(num).toLowerCase();
    if (from === undefined) {
      if (_startWith(num, '0x')) {
        from = 16;
      } else if (_startWith(num, '0')) {
        from = 8;
      } else {
        from = 10;
      }
    }
    num = parseInt(num, from);
    return num.toString(to);
  }
  ,

  _encodeHTML = function(str) {
    return _addEl({
      child : {text:str}
    }).innerHTML;
  }
  ,

  _decodeHTML = function(str) {
    return _getText(_addEl({
      html : str
    }))
  }

  ,
  _encodeURL = function(str) {
    return encodeURI(str)
  }
  ,

  _decodeURL = function(str) {
    return decodeURI(str)
  }
  ,

  /**
   * utf-8 encode, but not gb or else...
   * eg : %B9%FE = 哈 in gb, %E5%93%88 = 哈 in utf8
   */
  _encodePercent = function(str) {
    var result = '';
    _each(str.split(''), function(o) {
      var code = o.charCodeAt(0);
      if (code <= 127) {
        result += '%'+ _notationShift(code, 16);
      } else  {
        result += encodeURIComponent(o);
      }
    });
    return result;
  }
  ,

  _decodePercent = function(str) {
    return decodeURIComponent(str);
  }
  ,

  _encodeHex = function(str) {
    var result = [];
    _.e(str.split(''), function(o) {
      var code = o.charCodeAt(0);
      code = _notationShift(code, 16, 10);
      code = _strRepeat('0', 4 - code.length) + code;
      result[result.length] = '\\u' + code;
    });
    return result.join('');
  }
  ,

  _decodeHex = function(str) {
    var result = [];
    str = _trim(str);
    _.e(str.split('\\u'), function(o) {
      o.length > 0 && result.push(String.fromCharCode(_notationShift(o, 10, 16)));
    });
    return result.join('');
  }
  ,

  /**
   * encode numeric character reference
   */
  _encodeNCR = function(str) {
    var result = [];
    _.e(str.split(''), function(o) {
      var code = o.charCodeAt(0);
      result[result.length] = '&#' + code + ';';
    });
    return result.join('');
  }
  ,

  /**
   * decode numeric character reference
   */
  _decodeNCR = function(str) {
    return _decodeHTML(str);
  }
  ,

  _encode64 = function (sStr){
    var output = "", i = 0, len = sStr.length,
      chr1,chr2,chr3,
      enc1,enc2,enc3,enc4,
      base64keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    do {
      chr1 = sStr.charCodeAt(i++);
      chr2 = sStr.charCodeAt(i++);
      chr3 = sStr.charCodeAt(i++);
      enc1 = chr1>>2;
      enc2 = ((chr1&3)<<4)|(chr2>>4);
      enc3 = ((chr2&15)<<2)|(chr3>>6);
      enc4 = chr3&63;
      if (isNaN(chr2)) {
        enc3 = enc4 = 64;
      } else if(isNaN(chr3)) {
        enc4=64;
      }
        output = output + base64keyStr.charAt(enc1) + base64keyStr.charAt(enc2) +
          base64keyStr.charAt(enc3) + base64keyStr.charAt(enc4);
      } while(i<len);
    return output;
  },
  _decode64 = function(sStr) {
    var output = "",
      chr1, chr2, chr3,
      enc1, enc2, enc3, enc4,
      i = 0,
      base64keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    sStr = sStr.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    do {
      enc1 = base64keyStr.indexOf(sStr.charAt(i++));
      enc2 = base64keyStr.indexOf(sStr.charAt(i++));
      enc3 = base64keyStr.indexOf(sStr.charAt(i++));
      enc4 = base64keyStr.indexOf(sStr.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64) {
        output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
        output = output + String.fromCharCode(chr3);
      }
    } while (i < sStr.length);

    return output;
  }
  ,

  _stripTags = function(str) {
    return str.replace(/<\/?[^>]+>/gi, '');
  }
  ,

  _camelize = function(str) {
    var parts = str.split('_'), len = parts.length;
    if (len == 1) return parts[0];

    var camelized = str.charAt(0) == '_'
      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
      : parts[0];

    for (var i = 1; i < len; i++)
      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

    return camelized;
  }
  ,

  _undersore = function(str) {
    return str.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').toLowerCase()
  }
  ,

  _capitalize = function(str) {
    return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase()
  }
  ,

  /**
   * from : http://www.hedgerwow.com/360/dhtml/css-word-break.html 
   */
  _breakWord = function(dEl) {
    if(!dEl || dEl.nodeType !== 1){
      return false;
    } else if(dEl.currentStyle && typeof dEl.currentStyle.wordBreak === 'string'){
      //Lazy Function Definition Pattern, Peter's Blog
      //From http://peter.michaux.ca/article/3556
      _breakWord = function(dEl){
        //For Internet Explorer
        dEl.runtimeStyle.wordBreak = 'break-all';
        return true;
      }
      return _breakWord(dEl);
    }else if(document.createTreeWalker){
      _breakWord = function(dEl){
        //For Opera, Safari, and Firefox
        var dWalker = document.createTreeWalker(dEl, NodeFilter.SHOW_TEXT, null, false);
        var node,s,c = String.fromCharCode('8203');
        while (dWalker.nextNode())
        {
          node = dWalker.currentNode;
          //we need to trim String otherwise Firefox will display 
          //incorect text-indent with space characters
          s = _trim( node.nodeValue ) .split('').join(c);
          node.nodeValue = s;
        }
        return true;
      }
      return _breakWord(dEl);
    }else{
      return false;
    }
  }
  ,
  _sprintf = function(sTemplate) {
    var i = 1;
    while (arguments[i] !== undefined) {
      sTemplate = sTemplate.replace(/%s/, arguments[i++])
    }
    return sTemplate;
  }
  ,

  _startWith = function(str, pattern) {
    return str.indexOf(pattern) === 0;
  },

  _endWith = function(str, pattern) {
    var d = str.length - pattern.length;
    return d >= 0 && str.lastIndexOf(pattern) === d;
  }
  ,

  /**
   * Event utils
   */

  /**
   * function to start a ajax request
   * oCallback could have some methods: oCallback.o and oCallback.b, oCallback.timeout
   * ignore object oPost to start a GET request
   */
  _ajax = function(sUrl, oCallback, oPost) {
    var _sType, oAr;
    if (oPost === undefined) {
      _sType = 'GET';
    } else {
      _sType = 'POST';
      oPost = _isString(oPost) ? oPost : _.toJson(oPost);
    }
    oCallback.success = oCallback.o ? oCallback.o :
      function(o) {
        __.alert("Success!\nServer returns:" + o.responseText)
      };
    oCallback.failure = oCallback.b ? oCallback.b :
      function(o) {
        _log("Ajax request Failed!")
      };
    //set default timeout to 8 seconds
    oCallback.timeout = oCallback.timeout ? oCallback.timeout : 30000;
    oAr = _C.asyncRequest(_sType, sUrl, oCallback, oPost);
    return [oAr, oCallback];
  }
  ,
  _ajaxManager = (function() {
    /**
     * @param {_Req} obj
     */
    var _fnFinish = function(obj) {
      var __aTempReq = [];
      _each(_aRequesting, function(o, i) {
        if (o[0].id !== obj.id) {
          __aTempReq.push(o);
        }
      });
      _aRequesting = __aTempReq;
      _sendRequest();
    },
    _doAjax = function(obj) {
      var __od = obj.detail;
      __od.o = function(o) {
        _fnFinish(obj);
        __od.target && (_$(__od.target)[0].innerHTML = o.responseText);
        __od.fnSuccess && __od.fnSuccess(o.responseText);
      };
      __od.b = function(o) {
        _log('ajax request #' + obj.id + ' failed');
        _fnFinish(obj);
        __od.target && (_$(__od.target)[0].innerHTML = 'ajax request #' + obj.id + ' failed');
        if (__od.fnFailure) {
          __od.fnFailure(o.responseText);
        } else if (__od.fnFail) {
          __od.fnFail(o.responseText);
        }
      };
      return _ajax(_makeUrl(__od.sUrl, __od.oGet, __od.cache), __od, __od.sPost);
    },

      //array of _Req
      _aQueue = [],

      //0:_Req, 1:connection, 2:ocallback
      _aRequesting = [],
      _iId = 0,
      _makeUrl = function(sUrl, oGet, bCache) {
        if (sUrl.indexOf('?') < 0) {
          sUrl += '?';
        }
        oGet && _each(oGet, function(v,n) {
          sUrl += ['&', encodeURIComponent(n), '=', encodeURIComponent(v)].join('');
        }, true);
        /*
        if (!bCache) {
          sUrl += '&.strand=' + _rand(999999);
        }*/
        return _encodeURL(sUrl);
      }
      ,
      _sendRequest = function() {
        if (_aRequesting.length >= 2) {
          //waiting
          return;
        }
        var __newReq = _aQueue.shift(), __aResult;
        if (!__newReq) {
          return;
        }
        __aResult = _doAjax(__newReq);
        __aResult.unshift(__newReq);
        _aRequesting.push(__aResult);
      }
      ,
      /**
       * constructor of the queueing ajax request object
       * @constructor
       */
      _Req = function(oDetail, fnFilter) {
        this.id = _iId++;
        oDetail.cache = !!oDetail.cache;
        this.detail = oDetail;
        this.filter = fnFilter;
      };
      return {
        /**
         * @example  
         *  var i=0;
         *  for(var j=0;j<=10;j++) 
         *    __._.ajaxMgr.push({
         *      sUrl : '/behavior/rpc?doc&t='+Math.random(),
         *      fnSuccess : function(o) {
         *        console.log(i++);
         *      }
         *    })
         * @param {object} oDetail detail ajax config
         * @config {string} sUrl the url to be requested
         * @config {object} oGet name value pair of get parameters
         * @config {object} sPost the post content, will auto be json encode
         * @config {integer} timeout timeout of the request, milliseconds
         * @config {boolean} cache cache or not, default false
         * @config {function} fnSuccess on success handler
         * @config {function} fnFailure on failure handler
         * @config {function} fnFail alias of fnFailure
         * @config {dom|id|selector} target response will be target's innerHTML
         * @param {function} fnFilter queueing request will be aborted when filter return false
         */
        push : function(oDetail, fnFilter) {
          var oReq = new _Req(oDetail, fnFilter), _aTempQueue = [];
          if (fnFilter) {

            //filter the waiting queue
            _each(_aQueue, function(o, i) {
              if (fnFilter(o, oDetail)) {
                _aTempQueue.push(o);
              }
            });
            _aQueue = _aTempQueue;

            //filter the requesting queue
            _each(_aRequesting, function(o, i) {
              if (!fnFilter(o, oDetail)) {
                _C.abort(o[1]);
                _fnFinish(o[0]);
              }
            });
          }
          _aQueue.push(oReq);
          _sendRequest();
        }
      }
  })()
  ,

  _on =  function(el, sType, fn, obj, override) {
    sType = sType && sType.indexOf(':') > -1 ? 'dataavailable' : sType;

    if (_E.on(el, sType, fn, obj, override)) {
      __.listeners++;
      return true;
    }
    return false;
  }
  ,

  _off = function(el, sType, fn) {
    sType = sType && sType.indexOf(':') > -1 ? 'dataavailable' : sType;

    if (_E.removeListener(el, sType, fn)) {
      __.listeners--;
      return true;
    }
    return false;
  }
  ,
  /**
   * fire custom event
   */
  _fire = function(el, eventName, memo) {
    /* example:
     _.on(document, 'st:ohyeah', function(e) {
       if (e.eventName == 'st:ohyeah') {
         alert(e.memo.haha)
       }
     })
     _.fire(doucment, 'st:ohyeah', {'haha':123123})
    */
    var element = _$(el)[0] || document;
    if (element == document && document.createEvent && !element.dispatchEvent)
      element = document.documentElement;

    var ev;
    if (document.createEvent) {
      ev= document.createEvent("HTMLEvents");
      //initEvent function(type, bubbles, cancelable) 
      ev.initEvent("dataavailable", true, true);
    } else {
      ev= document.createEventObject();
      ev.eventType = "ondataavailable";
    }

    ev.eventName = eventName;
    ev.memo = memo || { };

    if (document.createEvent) {
      element.dispatchEvent(ev);
    } else {
      element.fireEvent(ev.eventType, ev);
    }
    return ev;
  }
  ,


  _getTarget = function(ev) {
    return _E.getTarget(ev);
  }
  ,

  _getRTarget = function(ev) {
    return _E.getRelatedTarget(ev);
  }
  ,

  _stopE = function(ev) {
    return _E.stopEvent(ev);
  }
  ,

  _getEvXY = function(ev) {
    return _E.getXY(ev);
  }
  ,

  _getKey = function(ev) {
    var keyObj = {
      shift : ev.shiftKey,
      alt : ev.altKey,
      ctrl : ev.ctrlKey,
      key : _E.getCharCode(ev)
    };
    return keyObj;
  }
  ,
  _onReady = function(fn, scope, override) {
    return _E.onDOMReady(fn, scope, override);
  }
  ,

  /**
   * Dom utils
   */

  /**
   * create (append) html element by object
   * @param {object} obj
   * @config {string} tag default div
   * @config {string|array} cls
   * @config {string} id
   * @config {string} html innerHTML
   * @config {string} css 
   * @config {string} value
   * @config {string} href
   * @config {object|array} child child node
   * @config {object} attrs attrs to be copied to the element
   * @config {string} text create a text node
   * config {string} src use attrs instead
   * config {object} parentN deprecated!!
   * @param {object|string} parent
   */
  _addEl = function(obj, parent) {// tag, cls, id, html, css, child, attrs, text, value
    var el,
      clsName = obj.cls,
      tagName = obj.tag;

    if (obj.text) {
      return _addText(obj.text, parent)
    }

    if (!tagName && parent && parent.tagName) {
      switch (parent.tagName.toLowerCase()) {
        case 'table' :
        case 'tbody' :
          tagName = 'tr';
          break;
        case 'tr' :
          tagName = 'td';
          break;
      }
    }

    tagName = tagName || 'div';

    el = document.createElement(tagName);
    if(!el) {
      return false;
    }

    if(obj.child) {
      if (!_isArray(obj.child)) {
        _addEl(obj.child, el)
      } else {
        _each(obj.child, function(oItem) {
          _addEl(oItem, el)
        })
      }
    }

    if (_isString(clsName)) {
      _addClass(el, clsName);
    } else if (_isArray(clsName)) {
      _each(clsName, function(oItem) {
        _addClass(el, oItem)
      });
    }
    _isString(obj.id) && (el.id = obj.id);

    obj.css && (el.style.cssText = obj.css);

    obj.value && (el.value = obj.value);

    obj.href && (el.href = obj.href);

    obj.html && (el.innerHTML = obj.html);

    obj.attrs && __.objExtend(el, obj.attrs);

    parent = _$(parent)[0];
    _isNode(parent) && (el = parent.appendChild(el));

    return el;
  }
  ,
  _remEl = function(els) {
    var rmFn = function(el) {
      el = _$(el);
      _each(el, function(o) {
        if (o && o.parentNode) {
          o.parentNode.removeChild(o);
        }
      });
    };
    if(_isArray(els)) {
      for(var i=els.length-1;i>-1;i--) {
        rmFn(els[i])
      }
    } else {
      rmFn(els);
    }
  }
  ,
  _insertBefore = function(newOne, oldOne) {
    if (oldOne.parentNode && oldOne.parentNode.insertBefore) {
      oldOne.parentNode.insertBefore(newOne, oldOne);
    }
  }
  ,
  
  _insertAfter = function (newNode,oldNode) {
    oldNode.nextSibling
      ? oldNode.parentNode.insertBefore(newNode, oldNode.nextSibling)
      : oldNode.parentNode.appendChild(newNode);
  }
  ,
  /**
   * remove whitespaces between nodes
   * @param {object|str} nodes
   */
  _normalizeNode = function (nodes){
    nodes = _$(nodes);
    _each(nodes, function(node) {
      if(node.hasChildNodes){
        var spaceTest = /^\s+$/;
        var children = node.childNodes;
        for(var i=0;children[i];i++){
          if(children[i].nodeType === _NODE_TYPE.TEXT_NODE){
            if(spaceTest.test(children[i].nodeValue)){
              children[i].parentNode.removeChild(children[i]);
            }
          }
        }
      }
    });
  }
  ,  
  _addText = function(text, parent) {
    text = document.createTextNode(text);
    parent && parent.appendChild(text);
    return text;
  }
  ,

  _getText = function(nodes) {
    nodes = _$(nodes);
    var txt = [];
    _each(nodes, function(node) {
      node = node.cloneNode(true);
      _normalizeNode(node);
      if (node && node.nodeType === _NODE_TYPE.TEXT_NODE) {
        txt[txt.length] =  node.nodeValue;
      } else if (node && node.nodeType === _NODE_TYPE.ELEMENT_NODE) {
        if (node.hasChildNodes()) {
          _each(node.childNodes, function(o) {
            txt[txt.length] = _getText(o);
          });
        }
      }
    });
    return txt.join('');
  }
  ,

  _addStyle = function(sText) {
    if (document.createStyleSheet) {
      //IE, create new css
      //!!remember the 31 limit
      var dCss = document.createStyleSheet('');
      dCss.cssText = sText;
    } else {
      _addEl({
        tag : 'style',
        attrs : { textContent : sText }
   //     html : sText
      }, 'head');
    }
  }
  ,
  _getP = function(el, property) {
    return _D.getStyle(el, property);
  }
  ,
  _setP = function(el, property, val) {
    return _D.setStyle(el, property, val);
  }
  ,
  _getElXY = function(el) {
    return _D.getXY(el);
  }
  ,
  _setElXY = function(el, pos) {
    return _D.setXY(el, pos, true);
  }
  ,
  _getPageXY = function() {
    return [_D.getDocumentWidth(), _D.getDocumentHeight()];
  }
  ,
  _getWindowXY = function() {
    return [_D.getViewportWidth(), _D.getViewportHeight()];
  }
  ,
  _getScrollXY = function() {
    var top = Math.max(document.documentElement.scrollTop, document.body.scrollTop),
      left = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
    return [left, top];
  }
  ,
  _getRegion = function(el) {
    return _D.getRegion(el);
  }
  ,
  _newRegion = function(t, r, b, l) {
    return new _YU.Region(t, r, b, l);
  }
  ,
  _newPoint = function(x, y) {
    return new _YU.Point(x, y);
  }
  ,
  _hasClass = function(el, className) {
    return _D.hasClass(el, className);
  }
  ,
  _addClass = function(el, className) {
    return _D.addClass(el, className);
  }
  ,
  _remClass = function(el, className) {
    return _D.removeClass(el, className);
  }
  ,

  /**
   * Other function
   */

  _fromJson = function(obj) {
    return _JSON.parse(obj);
  }
  ,
  _toJson = function(obj) {
    return _JSON.stringify(obj);
  }
  ,
  _rand = function(number) {
    var today = new Date(),
      seed = today.getTime(),
      percent;
    for(var i=1;i<=5;i++) {
      seed = (seed * 9301 + 49297) % 233280;
    }
    percent = seed / 233280.0;
    return Math.round(percent * number);
  }
  ,
  /**
   * get value of input element(textarea), and return a object of id:value pair
   * 
   */
  _getObjFromId = function(ary) {
    var _oResult = {};
    ary = _isArray(ary) ? ary : [ary];
    _each(ary, function(sId) {
      var _temp = _$(sId)[0];
      if(_temp && (typeof _temp.value != 'undefined')) {
        _oResult[sId] = _temp.value;
      } else if (_temp && _temp.innerHTML) {
        _oResult[sId] = _temp.innerHTML;
      } else {
        _oResult[sId] = null;
      }
    });
    return _oResult;
  }
  ,
  /**
   * a1 : the element to be D&D
   * withFade : bool, fade effect
   * restrict: object, {t,r,b,l}
   * fnUp : function(left, top, a1.zone){}, do after mouse release
   * fnMove : function(left, top, a1.zone){}, do onmove
   * 
   */
  _beginDrag = function (event, a1, withFade, restrict, fnUp, fnMove) {
    withFade = withFade === false ? false : true;
    var as = a1.style;
    a1.oriZ = _isEmpty(as.zIndex) ? 1 : as.zIndex;
    _setP(a1, 'zIndex', ++__.topLayer);
    if (!a1.moved) {
      a1.moved = true;
      if (as.position.toLowerCase().indexOf('absolute') == -1) {
        as.position = "relative";
      }

      if (as.left) {
        a1.oriL = parseInt(as.left);
      } else {
        a1.oriL = 0;
        as.left = '0px';
      }
      if (as.top) {
        a1.oriT = parseInt(as.top);
      } else {
        a1.oriT = 0;
        as.top = '0px';
      }
      if (restrict) {
        a1.zone = _newRegion(a1.oriT - restrict.t, a1.oriL + restrict.r,
          a1.oriT + restrict.b, a1.oriL - restrict.l);
      }
    }
    var x = parseInt(as.left),
      y = parseInt(as.top),
      a2 = withFade ? _getP(a1, 'opacity') : 0,
      a3 = event.clientX - x,
      a4 = event.clientY - y,
      a5 = function () {
        _off(document, 'mousemove', a6);
        _off(document, 'mouseup', a5);
        withFade && _setP(a1, 'opacity', a2);
        //withFade && changeOpac(a2, a1);
        _setP(a1, 'zIndex', a1.oriZ);
        __.topLayer--;
        __enableSelection(!!event.preventDefault);
        fnUp && fnUp(parseInt(as.left, 10), parseInt(as.top, 10), a1.zone);
      },
      a6 = function (ev) {
        var left = ev.clientX - a3, top = ev.clientY - a4;
        if (a1.zone) {
          var az = a1.zone;
          left = az.left > left ? az.left : left;
          left = az.right < left ? az.right : left;
          top = az.top > top ? az.top : top;
          top = az.bottom < top ? az.bottom : top;
        }
        as.left = left + "px";
        as.top = top + "px";
        fnMove && fnMove(left, top, a1.zone);
      },
      __disableSelection = function (isFF) {
        if (!isFF) {
          document.onselectstart = function() {return false;};
        } else {
          document.onmousedown = function (event) {event.preventDefault ()};
        }
      },
      __enableSelection = function (isFF) {
        if (!isFF) {
          document.onselectstart = null;
        } else {
          document.onmousedown=null;
        }
      };
    __disableSelection(!!event.preventDefault);
    //withFade && changeOpac(0.4, a1);
    withFade && _setP(a1, 'opacity', 0.4);;
    _on(document, 'mousemove', a6);
    _on(document, 'mouseup', a5);
  }
  ,
  /**
   * create an half transparent white div
   */
  _addIvDiv = (function (){
    var self = this,
      fn = function() {
      var id = arguments.callee.idPrefix,
        cz = ++arguments.callee.ivCount,
        newDiv = self.addEl({
          cls : "ivDiv",
          id : id + cz
        }, document.body),
        pageXY = _getPageXY();

      newDiv.oldBodyHeight = document.body.style.height;

      newDiv.innerHTML = '<table border="0"><tr><td><div>&nbsp;</div></td></tr></table>';
      _setP(newDiv, 'width', pageXY[0] + 'px');
      _setP(newDiv, 'height', pageXY[1] + 'px');
      _setP(newDiv, 'zIndex', ++__.topLayer);

      if (cz > 1) {
        var preDiv = self.$(id + (cz-1));
        _addClass(preDiv, 'transparent');
        _off(window, "resize", arguments.callee.ajSize);
      }

      _on(window, "resize", arguments.callee.ajSize, newDiv);
    };
    _addStyle(
'.ivDiv { position:absolute;top:0px;left:0px;background-color:#FFF;opacity:0.8;filter:alpha(opacity=80); }' +
'.ivDiv.transparent { background-color:transparent; }' +
'.ivDiv table { background-color:transparent;left:0px;top:0px; }'
    );
    fn.ivCount = 0;
    fn.idPrefix = "stFog";
    fn.ajSize = function (ev, div) {
      var xy = _getPageXY(), ds = div.style;
      ds.width = "auto";
      ds.height = "auto";
      ds.width = xy[0] + 'px';
      ds.height = xy[1] + 'px';
    };
    return fn;
  }).call(_)
  ,
  /**
   * remove the top half transparent white div
   */
  _remIvDiv = function() {
    var addfn = _addIvDiv,
      cz = addfn.ivCount;
    if(cz > 0) {
      addfn.ivCount --;
      __.topLayer--;
      _off(window, "resize", addfn.ajSize);
      _remEl(_$(addfn.idPrefix + cz));
      if (cz > 1) {
        var preDiv = _f(addfn.idPrefix + (cz-1));
        _remClass(preDiv, 'transparent');
        _on(window, "resize", addfn.ajSize, preDiv);
      }
    }
  }
  ,
	// Evalulates a script in a global context, from jquery
	_globalEval = function( data ) {
		data = _trim( data );

		if ( data ) {
			// Inspired by code by Andrea Giammarchi
			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
			var head = document.getElementsByTagName("head")[0] || document.documentElement,
				script = document.createElement("script");

			script.type = "text/javascript";
			if ( __.config.ua.ie )
				script.text = data;
			else
				_addText(data, script) ;

			head.appendChild( script );
			head.removeChild( script );
		}
	}
  ;
  
  __.objExtend(_, {
/**
 *  __ : global object
 *
 *    __.set : function(str, value)
 *    __.isSet : function(str)
 *    __.toCall : function(fn, fnOrStrJudge, iInterval)
 *    __.load : function()
 *    __.get : function(type, src, inHead)
 *    __.$.filter : function(aNodes, selector)
 *    __.$.test : function(oNode, selector)
 *
 *    __.objExtend : function(r, s, override)
 *    __.config : object 
 *      __.config.debug : boolean
 *    __.listeners : int
 *    __.topLayer : int
 *    __.Class: //__.Class.extend({}) 
 *    __.globalCheck : //__.globalCheck.init()
 *    __._ : object util
 */
    /**
     * Base utils
     */
    objExtend : __.objExtend,
    E : _EF,
    K : _K,
    OP : _OP, //object
    $ : _$, // function(sQueryOrDom, root, firstOnly),
    log : _log, // function(obj, bVarDump)
    getCookie: _getCookie, // function(name)
    setCookie: _setCookie, // function(name, value)
    range : _range, // function(start , end, pace)
    all : _all, // function(aAry, fn, bIsObject)
    any : _any, // function(aAry, fn, bIsObject)
    each : _each, // function(aAry, fn, bIsObject)
    e : _each, // short for each 
    f : _f, // function(sQueryOrDom)
    v : _v, // function(sQueryOrDom)
    reduce : _reduce, // function(aAry, fn, base, bIsObject)
    map : _map, // function(aAry, fn, bIsObj)
    a : _a, // function(aAry) array clone
    w : _w, // function(str)
    unique : _unique, // function(aAry, sorted)
    eachin : _eachin, // function(obj, fn)
    curry : _curry, // function(fn, [parms,...])
    keys : _keys, // function(aAry)
    values : _values, // function(aAry)
    compose : _compose, // function(fnWrap, fnParam)
    negate : _negate, // function(fn)
    dump : _dump, // function(obj, level)
    arrayRemove : _arrayRemove, // function(ary, from, to)

    /**
     * Language utils
     */
    getMergedObj : _getMergedObj, // function(oldOne, newOne)
    isArray : _isArray, // function(obj)
    isUndefined : _isUndefined, // function(obj)
    isNull : _isNull, // function(obj)
    isBoolean : _isBoolean, // function(obj)
    isFunction : _isFunction, // function(obj)
    isNumber : _isNumber, // function(obj)
    isInt : _isInt, // function(obj)
    isFloat : _isFloat, // function(obj)
    isObject : _isObject, // function(obj)
    isString : _isString, // function(obj)
    isEmpty : _isEmpty, // function(obj)
    isNode : _isNode, // function(obj, strict)
    inArray : _inArray, // function(obj, ary, strict)
    
    /**
     * String utils
     */
    trim : _trim, // function(str)
    truncate: _truncate, // function(str, len, truncation)
    strRepeat : _strRepeat, // function(str, times)
    notationShift : _notationShift, // function(num, to, from)
    encodeHTML : _encodeHTML, // function(str)
    decodeHTML : _decodeHTML, // function(str)
    encodeURL : _encodeURL, // function(str)
    decodeURL : _decodeURL, // function(str)
    encodePercent : _encodePercent, // function(str)
    decodePercent : _decodePercent, // function(str)
    encodeHex : _encodeHex, // function(str)
    decodeHex : _decodeHex, // function(str)
    encodeNCR : _encodeNCR, // function(str)
    decodeNCR : _decodeNCR, // function(str)
    encode64 : _encode64, // function(str)
    decode64 : _decode64, // function(str)
    stripTags : _stripTags, // function(str)
    camelize : _camelize, // function(str)
    underscore : _undersore, // function(str)
    capitalize : _capitalize, // function(str)
    breakWord: _breakWord, // function(dEl)
    sprintf : _sprintf, // function(sTemplate, [str...])
    startWith : _startWith, // function(str, pattern)
    endWith : _endWith, // function(str, pattern)

    /**
     * Event utils
     */
    ajax : _ajax, // function(sUrl, oCallback, oPost)
    p : _ajaxManager.push, // function(oDetail, fnFilter)
    on : _on, // function(el, sType, fn, obj, override)
    off : _off, // function(el, sType, fn)
    fire : _fire, // function(el, eventName, memo)
    getTarget: _getTarget, // function(ev)
    getRTarget: _getRTarget, // function(ev)
    stopEvent : _stopE, // function(ev)
    getEvXY : _getEvXY, // function(ev)
    getKey : _getKey, // function(ev)
    onReady : _onReady, // function(fn, scope, override)

  /**
   * Dom utils
   */
    addEl : _addEl, // function(obj, parent) obj = {tag, cls, id, html, css, child, attrs, text}
    remEl : _remEl, // function(els)
    insertBefore : _insertBefore, // function(newOne, oldOne)
    insertAfter : _insertAfter, // function (newNode,oldNode)
    normalizeNode : _normalizeNode, // function (nodes) remove whitespaces
    addText : _addText, // function(text, parent)
    getText : _getText, // function(nodes)
    addStyle : _addStyle, // function(sText)
    getP : _getP, // function(el, property)
    setP: _setP, // function(el, property, val)
    getElXY: _getElXY, // function(el)
    setElXY: _setElXY, // function(el, pos)
    getPageXY: _getPageXY, // function()
    getWindowXY: _getWindowXY, // function()
    getScrollXY : _getScrollXY, // function()
    getRegion : _getRegion, // function(el)
    newRegion : _newRegion, // function(t, r, b, l)
    newPoint : _newPoint, // function(x, y)
    hasClass: _hasClass, // function(el, className)
    addClass: _addClass, // function(el, className)
    remClass: _remClass, // function(el, className)

    /**
     * Other function
     */
    fromJson : _fromJson, // function(obj)
    toJson : _toJson, // function(obj)
    rand : _rand, // function(maxNumber)
    getObjFromId : _getObjFromId, // function(ary)
    beginDrag : _beginDrag, // function (event, a1, withFade, restrict, fnUp, fnMove)
    addIvDiv : _addIvDiv, // function()
    remIvDiv : _remIvDiv, // function()
    globalEval : _globalEval, // function(sText)
    dialog : (function(){//-su.dialog
      var _frame;
      return {
        alertDivId : 'stDomAlertDiv',
        dlgCount : 0,
        alertCount : 0,
        init : (function() {
          var fro = _addEl({cls : "movableHideDiv"}),
            inframe = _addEl({cls : 'i'}, fro), tl, ft;

          tl = _addEl({
            cls : 'mHDTitle',
            html : '<table><tbody><tr><td></td></tr></tbody></table>'
          }, inframe);
          _addEl({cls : 'mHDBd'}, inframe);
          ft = _addEl({
            cls : 'mHDBottom',
            html : '<table><tbody><tr><td style="text-align:right;color:#E00;"><span></span></td><td class="btna" style="text-align:right;"><input type="button" class="btnLogin" value="Ok" />&nbsp;<input type="button" class="btnLogin" value="Cancel"></td></tr></tbody></table>'
          }, inframe);

          _frame = fro;
        })()
        ,
        getFrame : function(id, width){
          var fr=_frame.cloneNode(true), ns=fr.firstChild.childNodes, self=this,
            btns=ns[2].getElementsByTagName('input');

          _setP(fr.firstChild, 'width', width+'px');
          ns[0].onmousedown = function(ev) {_.beginDrag(ev||window.event, this.parentNode.parentNode);};
          fr.tl = ns[0].getElementsByTagName('td')[0];
          fr.bd = ns[1];
          fr.ft = ns[2];
          fr.ok = btns[0];
          fr.cancel = btns[1];
          fr.msg = ns[2].getElementsByTagName('span')[0];

          fr.id = id;
          //on and off are used to just remove the div and dialog
          //remember to add unset your stuff in b4ok and b4cancel
          fr.on = function(){self.on(fr);};

          fr.b4off = function(){return true};

          fr.off = function(){fr.b4off() && self.off(fr);};

          fr.b4ok = function(){return true};
          fr.b4cancel = function(){return true};

          fr.clickok = function() {fr.b4ok() && fr.off();};
          fr.clickcancel = function() {fr.b4cancel() && fr.off();};

          fr.tibase = 1000 + this.dlgCount++ * 100;/* dialog tabindex begin from 1000, and for 1 dialog, 100 assigned */
          fr.ok.tabIndex = fr.tibase + 98;
          fr.cancel.tabIndex = fr.tibase + 99;

          return fr;
        }
        ,
        on : function(fr) {
          var wXY = _getWindowXY(),
            sXY = _getScrollXY(),
            _iDlgCount = _.dialog.dlgCount;// self = this;
          _setP(fr, 'opacity', 0);
          _addIvDiv();
          document.body.appendChild(fr);
          fr.style.position = 'absolute';
          fr.style.left = (wXY[0] - fr.offsetWidth) / 2 + sXY[0] + _iDlgCount*10 + 'px';
          fr.style.top = (wXY[1] - fr.offsetHeight) / 2 + sXY[1] + _iDlgCount*10 + 'px';
          fr.style.zIndex = ++__.topLayer;
          fr.ok.onclick = fr.clickok;
          fr.cancel.onclick = fr.clickcancel;
          _setP(fr, 'opacity', 85);
//            opacity(fr, 0, 85, 3000);
        }
        ,
        off : function(fr) {
          var sud = _.dialog;
          fr = _$(fr)[0];
          //opacity(fr, 85, 0, 200);
          fr.style.display = 'none';
          __.topLayer--;
          sud.dlgCount--;
          sud.alertCount--;
          document.body.removeChild(fr);
          _remIvDiv();
          /* Mem leak */
          fr = null;
        }
        ,
        alert : function(str, yes, no) {
          var fr=this.getFrame(this.alertDivId+this.alertCount++, 420);//tb=fr.tibase, self=this
          _addText('Message from stauren.net:', fr.tl);
          fr.bd.innerHTML = '<div id="qWbd"><table><tbody><tr><tr><td width="128"><img alt="notice" src="/misc/images/noticetriangle.gif" style="float:left;" /></td><td style="font-family:arial,helvetica,clean,sans-serif;width:290px;">'+ str +'</td></tr></tbody></table></div>';
          if (_isFunction(yes)) {
            fr.b4ok = function() {
              yes(fr);
              return true;
            };
          }
          if (_isFunction(no)) {
            fr.b4cancel = function() {
              no(fr);
              return true;
            };
          }
          fr.on();
        }
      }
    })()
  });

  _.$.filter = function(aNodes, sSelector) {
    if(_S) {
      return _S.filter(aNodes, sSelector)
    }
  };
  _.$.test = function(oNode, sSelector) {
    if(_S) {
      return _S.test(oNode, sSelector)
    }
  };
  __.$ = _.$;
  __.on = _.on;
  __.util = _;
  __.onReady = _.onReady;
  __.alert = function(str,yes,no){
    var sd = __._.dialog;
    sd.alert.apply(sd, arguments)
  };
}, 'YAHOO');

})(window);

/* class inherit sample (YAHOO edition, with enclosure, and private member, not prototype way)
var fn1 = function(p1) {
  //private member
  var in1;

  //initialize 
  (function(){
    in1 = p1 * 2;
  })();

  //public member
  var publicM = {
    getIn1 : function() {
      alert(in1);
    },
    setP1 : function(n) {
      in1 = n * 2;
    }
  };

  return publicM;
};
var fn2 = function(p1, p2) {
  //call the super constructor, could be called else where(eg: in the initializer)
  var superObj = new arguments.callee.superclass.constructor(p1);

  //private member
  var in2;

  //initialize 
  (function(){
    in2 = p2 * 3;
  })();

  //public member
  var publicM = {
    out1 : 'I am a public member',
    getIn2 : function() {
      alert(in2);
    },
    alertOut1 : function() {
      //use this to reference
      //can not reference to in2: (typeof this.in2 == undefined)
      alert(this.out1);
    }
  };

  __._.objExtend(publicM, superObj, false);
  
  return publicM;
};
__._.classExtend(fn2, fn1);//old
var obj_fn2 = new fn2(4,5);
obj_fn2.getIn1();
obj_fn2.getIn2();
obj_fn2.setP1(123);
obj_fn2.getIn1();
*/
///////////////////////////////////////////////////////////////////////////////////////
/*
    classExtend : function(subc, superc) {
      function buildSuperChain(superc , ary )  {
        ary.push(superc);
        if (typeof superc.__superclasses__ == "object") {
          for (var i=0; i < superc.__superclasses__.length; i++){
            buildSuperChain(superc.__superclasses__[i], ary);
          }
        }
      }
      
      if (typeof subc.prototype.constructor.__superclasses__ == "undefined") {
        subc.prototype.constructor.__superclasses__ = new Array();
      }
      
      buildSuperChain(superc, subc.prototype.constructor.__superclasses__);
      
      for (prop in superc.prototype) {
        if (typeof superc.prototype[prop] == "function") {
          subc.prototype[prop] = superc.prototype[prop];
        }
      }
    }
    ,*/
/* prototype edition example
function fn1(p1) {
  //constructor, all none-method properties
  this.in1 = p1;

  if (typeof fn1.prototype._stinited == 'undefined') {
    fn1.prototype.get1Sq = function() {
      alert(this.in1*this.in1);
    };

    fn1.prototype._stinited = true;
  }
}
function fn2(p1, p2) {
  fn1.call(this, p1);
  this.in2 = p2;

  if (typeof fn2.prototype._stinited == 'undefined') {
    __._.classExtend(fn2, fn1);

    fn2.prototype.get2Tri = function() {
      alert(this.in2*this.in2*this.in2);
    };

    fn2.prototype._stinited = true;
  }
}

var obj_fn2 = new fn2(4,5);
obj_fn2.get1Sq();
obj_fn2.get2Tri();

*/
